package com.higgins.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.higgins.client.GreetingService;
import com.higgins.client.dataModel.CoveringLetterDTO;
import com.higgins.client.dataModel.LawFirmDTO;
import com.higgins.client.dataModel.LawFirmTypeDTO;
import com.higgins.client.dataModel.RecipientDTO;
import com.higgins.client.dataModel.RegionDTO;
import com.higgins.client.dataModel.SectorDTO;
import com.higgins.client.dataModel.StrategyDTO;
import com.higgins.client.dataModel.StrategyRecipientCountDTO;
import com.higgins.client.dataModel.StrategyRecipientDTO;
import com.higgins.server.agentapp.service.AgentAppServiceImpl;
import com.higgins.shared.FieldVerifier;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class GreetingServiceImpl extends com.seguedevelopment.gwtrpccommlayer.server.GwtRpcCommLayerServlet implements
		GreetingService {
	private static final Logger log = Logger.getLogger(GreetingServiceImpl.class.getName());
	private EntityManagerFactory emfInstance = Persistence
			.createEntityManagerFactory("com.higgins.server.jpa");

	public GreetingServiceImpl()	{
		 
	}
	public void doGet(HttpServletRequest req, HttpServletResponse resp)	throws IOException	{
		log.info("Ping Received!");
	}	
	public void setStrategy(String name)	{
		Strategy strategy = new Strategy();
		strategy.setName(name);
		strategy.setTimestamp(new Date());

		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		entityManager.persist(strategy);
		entityManager.getTransaction().commit();
		entityManager.close();		
	}
	
	public Strategy getStrategy(String name)	{
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from Strategy s where upper(s.name) like (:arg1)");
		query.setParameter("arg1", name);
		List<Strategy> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		entityManager.close();	
		return null;
	}

	@Override
	public List<StrategyDTO> retrieveStrategys()
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from Strategy s");
		List<Strategy> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<StrategyDTO> dtoList = new ArrayList<StrategyDTO>();
		for (Strategy strategy:list)	{
			StrategyDTO dto = strategy.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;
	}
	
	public Strategy retrieveStrategy(EntityManager entityManager, Long id) throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from Strategy s where s.id = :arg1");
		query.setParameter("arg1", id);
		List<Strategy> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		else 
			return null;
	}
		
	@Override
	public String updateStrategy(StrategyDTO dto)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		
		Strategy strategy = dto.getId()!=null?retrieveStrategy(entityManager, dto.getId()):new Strategy();
		if (dto.getId()==null)	{
			strategy.setStatus(0);
			strategy.setTimestamp(new Date());
		}
		strategy.update(dto);	
		CoveringLetterDTO coveringLetterDTO = dto.getCoveringLetterDTO();
		if (coveringLetterDTO!=null)	{
			strategy.setCoveringLetter(retrieveCoveringLetter(entityManager, coveringLetterDTO.getId()));
		}
		
		entityManager.persist(strategy);
		entityManager.getTransaction().commit();
		entityManager.close();		
		return strategy.getId().toString();
	}

	@Override
	public List<CoveringLetterDTO> retrieveCoveringLetters()
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from CoveringLetter c");
		List<CoveringLetter> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<CoveringLetterDTO> dtoList = new ArrayList<CoveringLetterDTO>();
		for (CoveringLetter coveringLetter:list)	{
			CoveringLetterDTO dto = coveringLetter.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;
	}

	public CoveringLetter retrieveCoveringLetter(EntityManager entityManager, Long id) throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from CoveringLetter c where c.id = :arg1");
		query.setParameter("arg1", id);
		List<CoveringLetter> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		else 
			return null;
	}
	
	
	@Override
	public String updateCoveringLetter(CoveringLetterDTO dto)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		
		CoveringLetter coveringLetter = dto.getId()!=null?retrieveCoveringLetter(entityManager, dto.getId()):new CoveringLetter();
		coveringLetter.update(dto);		
		entityManager.persist(coveringLetter);
		entityManager.getTransaction().commit();
		entityManager.close();		
		return coveringLetter.getId().toString();
	}
	
	@Override
	public List<RegionDTO> retrieveRegions()
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from Region c");
		List<Region> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<RegionDTO> dtoList = new ArrayList<RegionDTO>();
		for (Region region:list)	{
			RegionDTO dto = region.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;
	}

	public Region retrieveRegion(EntityManager entityManager, Long id) throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from Region c where c.id = :arg1");
		query.setParameter("arg1", id);
		List<Region> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		else 
			return null;
	}
	
	@Override
	public String updateRegion(RegionDTO dto)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		
		Region region = dto.getId()!=null?retrieveRegion(entityManager, dto.getId()):new Region();
		region.update(dto);		
		entityManager.persist(region);
		entityManager.getTransaction().commit();
		entityManager.close();		
		return region.getId().toString();
	}
	
	

	
	@Override
	public List<SectorDTO> retrieveSectors()
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from Sector c");
		List<Sector> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<SectorDTO> dtoList = new ArrayList<SectorDTO>();
		for (Sector sector:list)	{
			SectorDTO dto = sector.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;
	}

	public Sector retrieveSector(EntityManager entityManager, Long id) throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from Sector c where c.id = :arg1");
		query.setParameter("arg1", id);
		List<Sector> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		else 
			return null;
	}
	
	@Override
	public String updateSector(SectorDTO dto)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		
		Sector sector = dto.getId()!=null?retrieveSector(entityManager, dto.getId()):new Sector();
		sector.update(dto);		
		entityManager.persist(sector);
		entityManager.getTransaction().commit();
		entityManager.close();		
		return sector.getId().toString();
	}
	
	
	
   @Override
    public List<LawFirmTypeDTO> retrieveLawFirmTypes()
            throws IllegalArgumentException {
        EntityManager entityManager = emfInstance.createEntityManager();
        Query query = entityManager.createQuery( "from LawFirmType c");
        List<LawFirmType> list = query.getResultList();
        System.out.println("Size of list = " + list.size());
        List<LawFirmTypeDTO> dtoList = new ArrayList<LawFirmTypeDTO>();
        for (LawFirmType lawFirmType:list)    {
            LawFirmTypeDTO dto = lawFirmType.toDTO();
            dtoList.add(dto);
        }
        entityManager.close();  
        return dtoList;
    }
	   

	@Override
	public List<LawFirmDTO> retrieveLawFirms()
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from LawFirm c");
		List<LawFirm> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<LawFirmDTO> dtoList = new ArrayList<LawFirmDTO>();
		for (LawFirm lawFirm:list)	{
			LawFirmDTO dto = lawFirm.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;
	}
	
    @Override
    public List<LawFirmDTO> retrieveLawFirms(SectorDTO sectorDTO, LawFirmTypeDTO lawFirmTypeDTO)
            throws IllegalArgumentException {
        EntityManager entityManager = emfInstance.createEntityManager();
        String queryString = "from LawFirm c ";
        if (sectorDTO!=null || lawFirmTypeDTO!=null)    {
            queryString = queryString + " where ";
        }
        if (sectorDTO!=null)    {
            queryString = queryString + " c.sectorId = :arg1 ";
        }
        if (lawFirmTypeDTO!=null)    {
            queryString = queryString + (sectorDTO!=null?" and ":"") + " c.lawFirmTypeId = :arg2 ";
        }
        Query query = entityManager.createQuery( queryString);
        if (sectorDTO!=null)    {
            query.setParameter("arg1", sectorDTO.getId());
        }
        if (lawFirmTypeDTO!=null)    {
            query.setParameter("arg2", lawFirmTypeDTO.getId());
        }
        List<LawFirm> list = query.getResultList();
        System.out.println("Size of list = " + list.size());
        List<LawFirmDTO> dtoList = new ArrayList<LawFirmDTO>();
        for (LawFirm lawFirm:list)  {
            LawFirmDTO dto = lawFirm.toDTO();
            dtoList.add(dto);
        }
        entityManager.close();  
        return dtoList;
    }

	public LawFirm retrieveLawFirm(EntityManager entityManager, Long id) throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from LawFirm c where c.id = :arg1");
		query.setParameter("arg1", id);
		List<LawFirm> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		else 
			return null;
	}
	
	@Override
	public String updateLawFirm(LawFirmDTO dto)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		
		LawFirm lawFirm = dto.getId()!=null?retrieveLawFirm(entityManager, dto.getId()):new LawFirm();
		lawFirm.update(dto);		
		entityManager.persist(lawFirm);
		entityManager.getTransaction().commit();
		entityManager.close();		
		return lawFirm.getId().toString();
	}

	@Override
	public List<RecipientDTO> retrieveRecipients(RegionDTO regionDTO,
			SectorDTO sectorDTO) throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from Recipient c where c.region = :arg1 and c.sector = :arg2 ");
		query.setParameter("arg1", retrieveRegion(entityManager, regionDTO.getId()));
		query.setParameter("arg2", retrieveSector(entityManager, sectorDTO.getId()));
		List<Recipient> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<RecipientDTO> dtoList = new ArrayList<RecipientDTO>();
		for (Recipient recipient:list)	{
			RecipientDTO dto = recipient.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;	
	}

	@Override
	public List<RecipientDTO> retrieveRecipients(StrategyDTO strategyDTO) throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		
		Query query = entityManager.createQuery("select r from Recipient r, StrategyRecipient c where r.id = c.recipientId and c.strategyId = :arg1 ");	
//		query = entityManager.createQuery( "from Recipient c where c.strategy = :arg1 ");
		query.setParameter("arg1", strategyDTO.getId());
		List<Recipient> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		List<RecipientDTO> dtoList = new ArrayList<RecipientDTO>();
		for (Recipient recipient:list)	{
			RecipientDTO dto = recipient.toDTO();
			dtoList.add(dto);
		}
		entityManager.close();	
		return dtoList;	
	}

	public Recipient retrieveRecipient(EntityManager entityManager, Long id) throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from Recipient c where c.id = :arg1");
		query.setParameter("arg1", id);
		List<Recipient> list = query.getResultList();
		System.out.println("Size of list = " + list.size());
		if (list.size() > 0)
			return list.get(0);
		else 
			return null;
	}	
	
	@Override
	public String updateRecipient(RecipientDTO recipientDTO)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		
		Recipient recipient = recipientDTO.getId()!=null?retrieveRecipient(entityManager, recipientDTO.getId()):new Recipient();
		recipient.update(recipientDTO);	
		LawFirmDTO lawFirmDTO = recipientDTO.getLawFirmDTO();
		if (lawFirmDTO!=null)	{
			recipient.setLawFirm(retrieveLawFirm(entityManager, lawFirmDTO.getId()));
		}
		RegionDTO regionDTO = recipientDTO.getRegionDTO();
		if (regionDTO!=null)	{
			recipient.setRegion(retrieveRegion(entityManager, regionDTO.getId()));
		}
		SectorDTO sectorDTO = recipientDTO.getSectorDTO();
		if (sectorDTO!=null)	{
			recipient.setSector(retrieveSector(entityManager, sectorDTO.getId()));
		}
		entityManager.persist(recipient);
		entityManager.getTransaction().commit();
		entityManager.close();
		return recipient.getId().toString();
	}
	@Override
	public String setStrategyRecipient(StrategyRecipientDTO strategyRecipientDTO)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();

		StrategyRecipient strategyRecipient = retrieveStrategyRecipients(entityManager, strategyRecipientDTO);
		if (strategyRecipient==null)	{
			strategyRecipient = new StrategyRecipient();
			strategyRecipient.setStatus(0);
		}
		strategyRecipient.update(strategyRecipientDTO);
		if (strategyRecipient.getLawFirmId()==null)		{
			populateLawFirm(entityManager, strategyRecipient);
		}
		entityManager.persist(strategyRecipient);
		
		entityManager.getTransaction().commit();
		Long id = strategyRecipient.getId();
		entityManager.close();
		return id!=null?id.toString():"";
	}
	
	public void populateLawFirm(EntityManager entityManager, StrategyRecipient strategyRecipient)	{
		Recipient recipient = retrieveRecipient(entityManager, strategyRecipient.getRecipientId());
		strategyRecipient.setLawFirmId(recipient.getLawFirm()!=null?recipient.getLawFirm().getId():null);
	}
	
	public StrategyRecipient retrieveStrategyRecipients(EntityManager entityManager, StrategyRecipientDTO strategyRecipientDTO)
			throws IllegalArgumentException {
		Query query = entityManager.createQuery( "from StrategyRecipient c where c.recipientId = :arg1 and c.strategyId = :arg2");
		query.setParameter("arg1", strategyRecipientDTO.getRecipientId());
		query.setParameter("arg2", strategyRecipientDTO.getStrategyId());
		List<StrategyRecipient> list = query.getResultList();

		for (StrategyRecipient strategyRecipient:list)	{
			return strategyRecipient;
		}
		
		return null;
	}
	@Override
	public String removeStrategyRecipient(StrategyRecipientDTO strategyRecipientDTO)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();

		Query query = entityManager.createQuery( "from StrategyRecipient c where c.recipientId = :arg1 and c.strategyId = :arg2");
		query.setParameter("arg1", strategyRecipientDTO.getRecipientId());
		query.setParameter("arg2", strategyRecipientDTO.getStrategyId());
		List<StrategyRecipient> list = query.getResultList();

		for (StrategyRecipient strategyRecipient:list)	{
			strategyRecipient.setDisabled(true);
			entityManager.persist(strategyRecipient);
		}
		entityManager.getTransaction().commit();
		
		entityManager.close();
		return "";
	}
	@Override
	public List<StrategyRecipientDTO> retrieveStrategyRecipients(
			Long strategyId, Long regionId, Long sectorId)
			throws IllegalArgumentException {

		EntityManager entityManager = emfInstance.createEntityManager();
//		Query query = entityManager.createQuery( "from StrategyRecipient c where c.strategyId = :arg1 and c.regionId = :arg2 and c.sectorId = :arg3");
		Query query = entityManager.createQuery( "from StrategyRecipient c where c.regionId = :arg2 and c.sectorId = :arg3");
//		query.setParameter("arg1", strategyId);
		query.setParameter("arg2", regionId);
		query.setParameter("arg3", sectorId);
		List<StrategyRecipient> list = query.getResultList();
		
		List<StrategyRecipientDTO> dtoList = new ArrayList<StrategyRecipientDTO>();
		for (StrategyRecipient strategyRecipient:list)	{
			StrategyRecipientDTO dto = strategyRecipient.toDTO();
			if (dto.getDisabled()==null || (!dto.getDisabled()))
				dtoList.add(dto);
		}
		entityManager.close();
		return dtoList;	
	}

	@Override
	public StrategyRecipientCountDTO retrieveStrategyRecipientCount(
			Long strategyId) throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		Query query = entityManager.createQuery( "from StrategyRecipient c where c.strategyId = :arg1 and c.disabled != :arg2");
		query.setParameter("arg1", strategyId);
		query.setParameter("arg2", true);
		List<StrategyRecipient> list = query.getResultList();
		StrategyRecipientCountDTO count = new StrategyRecipientCountDTO();
		count.setStrategyId(strategyId);
		count.setReceipientCount(list.size());
		return count;
	}

	@Override
	public String publishStrategy(Long strategyId)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		Strategy strategy = retrieveStrategy(entityManager, strategyId);
		strategy.setStatus(1);
		entityManager.persist(strategy);
		
		// Publish all the StrategyRecipients also
		
		entityManager.getTransaction().commit();
		entityManager.close();
		return strategy.getId().toString();
	}	
	@Override
	public String unpublishStrategy(Long strategyId)
			throws IllegalArgumentException {
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		Strategy strategy = retrieveStrategy(entityManager, strategyId);
		strategy.setStatus(0);
		entityManager.persist(strategy);
		
		// UnPublish all the StrategyRecipients also

		entityManager.getTransaction().commit();
		entityManager.close();
		return strategy.getId().toString();
	}	
	@Override
	public Long retrieveLawFirmUnavailableStatus(RecipientDTO recipientDTO)	{
		EntityManager entityManager = emfInstance.createEntityManager();
		entityManager.getTransaction().begin();
		LawFirmDTO lawFirmDTO = recipientDTO.getLawFirmDTO();
		if (lawFirmDTO!=null)	{
			Query query = entityManager.createQuery( "select count(c.id) from StrategyRecipient c where c.lawFirmId = :arg1 and c.disabled = :arg2 ");
			query.setParameter("arg1", lawFirmDTO.getId());
			query.setParameter("arg2", false);
			List<Long> list = query.getResultList();
			if (list.size() > 0)	{
				Long count = list.get(0);
				if (count > 0)	{
					return recipientDTO.getId();
				}
			}
//			List<StrategyRecipient> list = query.getResultList();
//			if (list.size() > 0)	{
//				return recipientDTO.getId();
//			}
		}
		entityManager.getTransaction().commit();
		entityManager.close();
		return null;
		
	}
	
}
